package ffmpeg

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
)

// ExecCmd 执行CMD命令
func (f *SFFmpeg) executeCommand(cmd *exec.Cmd) error {
	fmt.Println(`执行命令开始`, cmd.Args)
	// 创建管道来捕获标准输出和标准错误
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}

	stderr, err := cmd.StderrPipe()
	if err != nil {
		return err
	}

	// 启动ffmpeg命令
	if err = cmd.Start(); err != nil {
		return fmt.Errorf(`命令启动失败%w`, err)
	}
	// 异步控制
	var wg sync.WaitGroup
	wg.Add(2)

	// 异步读取并打印标准输出
	go func() {
		defer wg.Done()
		scanner := bufio.NewScanner(stdout)
		for scanner.Scan() {
			// 这里可以添加逻辑来过滤和格式化输出
			// 例如，只打印包含"frame"或"time"的行
			text := scanner.Text()
			fmt.Println(`标准输出：`, text)
			if strings.Contains(text, "frame") || strings.Contains(text, "time=") {
				fmt.Println(text)
			}
		}
		// 打印标准输出错误
		if err = scanner.Err(); err != nil {
			fmt.Println("读取标准输出时出错:", err)
		}
	}()

	// 异步读取并打印标准错误（通常用于打印错误消息）
	go func() {
		defer wg.Done()
		scanner := bufio.NewScanner(stderr)
		for scanner.Scan() {
			fmt.Println(scanner.Text())
		}
		if err = scanner.Err(); err != nil {
			fmt.Println("读取标准错误时出错:", err)
		}
	}()

	wg.Wait() // 等待异步完成
	// 等待ffmpeg命令完成
	if err = cmd.Wait(); err != nil {
		return fmt.Errorf(`FFmpeg命令执行完成%w`, err)
	}
	return nil
}

// EnsureDir 检查给定路径的目录是否存在，如果不存在则创建它
func (f *SFFmpeg) EnsureDir(dir string) error {
	// 获取目录的绝对路径
	absDir, err := filepath.Abs(dir)
	if err != nil {
		return err
	}

	// 使用os.Stat函数检查目录是否存在
	stat, err := os.Stat(absDir)
	if err == nil {
		// 如果路径存在，判断是否是目录
		if !stat.IsDir() {
			return fmt.Errorf("路径 %s 存在但不是目录", absDir)
		}
		// 目录已存在，无需操作
		return nil
	}

	// 如果os.Stat返回的错误是文件或目录不存在的错误，则尝试创建目录
	if os.IsNotExist(err) {
		// 创建目录，包括所有必要的上级目录
		err = os.MkdirAll(absDir, 0755) // 0755 是常见的目录权限
		if err != nil {
			return err
		}
		return nil
	}

	// 如果返回的不是“不存在”的错误，则返回原错误
	return err
}

// IsFileExists 检查文件是否存在
func (f *SFFmpeg) IsFileExists(src string) bool {
	absSrc, err := filepath.Abs(src)
	if err != nil {
		return false
	}
	// 获取文件信息是否存在
	if _, err = os.Stat(absSrc); err != nil {
		return false
	}
	return true
}
